###
import json
import os
from typing import Dict, Any
from datetime import datetime

from Assignment_and_Grading.course_task_classes import Quiz

class DataPersistence:
    """Handles saving and loading of assignment/grade data to storage"""

    def __init__(self, data_file):
        """Initialize with the path to the data file"""
        self.data_file = data_file
    
    def save_assignments(self, assignments, file_path):
        """Save assignment/quiz data to JSON file"""
        try:
            serialized_data = []
            for task in assignments:
                # 统一的任务数据结构
                task_data = {
                    "type": task.__class__.__name__,
                    "id": getattr(task, "assignment_id", getattr(task, "quiz_id", None)),
                    "title": getattr(task, "assignment_title", getattr(task, "quiz_title", None)),
                    "content": getattr(task, "assignment_content", None),
                    "due_date": task.due_date.isoformat(),
                    "course_id": task.course.course_id if task.course else None,
                    "submissions": {}
                }
                
                # 统一的提交数据结构
                if hasattr(task, "submissions"):
                    for sid, sub in task.submissions.items():
                        task_data["submissions"][sid] = {
                            "content": sub.get("content", sub.get("answers", None)),
                            "submit_time": sub["submit_time"].isoformat(),
                            "is_late": sub["is_late"],
                            "score": sub.get("score", None),
                            "status": sub.get("status", "submitted")  # 保存状态字段
                        }
                
                # Quiz特定属性
                if isinstance(task, Quiz):
                    task_data.update({
                        "questions": task.questions,
                        "time_limit": task.time_limit
                    })
                
                serialized_data.append(task_data)
            
            with open(file_path, 'w') as f:
                json.dump(serialized_data, f, indent=2)
            return True
        except Exception as e:
            print(f"Error saving assignments: {str(e)}")
        
    def load_data(self) -> Dict[str, Any]:
        """Load data from the JSON file.
        
        Returns:
            Dict[str, Any]: The loaded data, or default structures if file not found.
        """
        try:
            if os.path.exists(self.data_file):
                with open(self.data_file, "r", encoding="utf-8") as file: #encoding=utf-8的意思是为了避免在读取文件时出现编码错误(例如文件中包含非ASCII字符)
                    return json.load(file)
                
            else:
                return {
                    "users": [],
                    "courses": [],
                    "progress": {},
                    "grades": {}
                }
        except Exception as e:
            print(f"Error loading data: {e}")
            return {
                    "users": [],
                    "courses": [],
                    "progress": {},
                    "grades": {}
                }
        
    def save_data(self, data: Dict[str, Any]) -> None:
        """Save data to the JSON file.
            
        Args:
            data (Dict[str, Any]): The data to be saved.
        """
        try:
            # 添加default参数处理datetime对象序列化
            def datetime_serializer(obj):
                if isinstance(obj, datetime):
                    return obj.isoformat()
                raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
            
            with open(self.data_file, "w", encoding="utf-8") as file:
                json.dump(data, file, ensure_ascii=False, indent=4, default=datetime_serializer)
        except Exception as e:
            print(f"Error saving data: {e}")

    def add_user(self, user_data: Dict[str, Any]) -> None:
        """Add a new user to the data file incrementally.
        
        Args:
            user_data (Dict[str, Any]): The user data to add.
        """

        # Load existing data
        existing_data = self.load_data()
            
        # Check if user already exists by user_id AND username
        user_id = user_data.get("user_id")
        username = user_data.get("username")
            
        user_exists = False
        for i, user in enumerate(existing_data["users"]):
            if user.get("user_id") == user_id and user.get("username") == username:
                # 更新现有用户
                existing_data["users"][i] = user_data
                user_exists = True
                break
    
        if not user_exists:
            # 添加新用户到现有用户列表
            existing_data["users"].append(user_data)
    
            # 保存更新后的数据
        self.save_data(existing_data)
            

    def update_user(self, user_id: str, updated_data: Dict[str, Any]) -> None:
        """Update an existing user in the data file incrementally.
        
        Args:
            user_id (str): The ID of the user to update.
            updated_data (Dict[str, Any]): The updated user data.
        """
        try:
            # Load existing data
            existing_data = self.load_data()
            
            # Find and update the user
            for i, user in enumerate(existing_data["users"]):
                if user.get("user_id") == user_id:
                    # Merge existing data with updates
                    existing_data["users"][i].update(updated_data)
                    break
            else:
                print(f"⚠️  User {user_id} not found for update")
                return
            
            # Save updated data
            self.save_data(existing_data)
            print(f"✅ User {user_id} updated incrementally")
        except Exception as e:
            print(f"Error updating user: {e}")

    def add_course(self, course_data: Dict[str, Any]) -> None:
        """Add a new course to the data file incrementally.
        
        Args:
            course_data (Dict[str, Any]): The course data to add.
        """
        try:
            # Load existing data
            existing_data = self.load_data()
            
            # Check if course already exists
            course_id = course_data.get("course_id")
            for i, course in enumerate(existing_data["courses"]):
                if course.get("course_id") == course_id:
                    # Update existing course
                    existing_data["courses"][i] = course_data
                    break
            else:
                # Add new course
                existing_data["courses"].append(course_data)
            
            # Save updated data
            self.save_data(existing_data)
            print(f"✅ Course {course_id} saved incrementally")
        except Exception as e:
            print(f"Error adding course: {e}")

    def update_progress(self, user_id: str, course_id: str, progress_data: Dict[str, Any]) -> None:
        """Update progress records with optimized structure"""
        try:
            # 加载现有数据
            existing_data = self.load_data()
            
            # 确保progress字段存在并使用优化的三级结构
            if "progress" not in existing_data:
                existing_data["progress"] = {}
            
            # 优化的三级结构: progress[course_id][user_id] = progress_data
            if course_id not in existing_data["progress"]:
                existing_data["progress"][course_id] = {}
            
            existing_data["progress"][course_id][user_id] = progress_data
            
            # 保存更新后的数据
            self.save_data(existing_data)
            print(f"✅ Progress for {user_id} in {course_id} updated incrementally")
        except Exception as e:
            print(f"Error updating progress: {e}")

    def update_grade(self, user_id: str, course_id: str, assignment_id: str, grade_data: Dict[str, Any]) -> None:
        """Update grade records with optimized four-level structure"""
        try:
            # 加载现有数据
            existing_data = self.load_data()
            
            # 确保grades字段存在并使用优化的四级结构
            if "grades" not in existing_data:
                existing_data["grades"] = {}
            
            # 优化的四级结构: grades[course_id][user_id][assignment_id] = grade_data
            if course_id not in existing_data["grades"]:
                existing_data["grades"][course_id] = {}
            if user_id not in existing_data["grades"][course_id]:
                existing_data["grades"][course_id][user_id] = {}
            
            existing_data["grades"][course_id][user_id][assignment_id] = grade_data
            
            # 保存更新后的数据
            self.save_data(existing_data)
            print(f"✅ Grade for {user_id} in {course_id} (assignment {assignment_id}) updated incrementally")
        except Exception as e:
            print(f"Error updating grade: {e}")

    def sync_user_course_relationships(users, courses):
        """同步用户和课程之间的关系,确保双向引用一致性"""
        # 1. 建立ID映射
        user_id_map = {user.user_id: user for user in users}
        course_id_map = {course.course_id: course for course in courses}
    
        # 2. 从学生端同步
        for user in users:
            if hasattr(user, 'role') and user.role == 'student' and hasattr(user, 'enrolled_courses'):
                # 确保学生的enrolled_courses是集合类型,避免重复
                if isinstance(user.enrolled_courses, list):
                    user.enrolled_courses = list(set(user.enrolled_courses))
            
                for course_id in user.enrolled_courses:
                    if course_id in course_id_map:
                        course = course_id_map[course_id]
                        # 确保课程的enrolled_students是集合类型
                        if not hasattr(course, 'enrolled_students'):
                            course.enrolled_students = []
                        elif isinstance(course.enrolled_students, list):
                            course.enrolled_students = list(set(course.enrolled_students))
                    
                        # 确保学生ID在课程的enrolled_students中
                        if user.user_id not in course.enrolled_students:
                            course.enrolled_students.append(user.user_id)
    
        # 3. 从课程端同步
        for course in courses:
            if hasattr(course, 'enrolled_students'):
                for student_id in course.enrolled_students:
                    if student_id in user_id_map:
                        user = user_id_map[student_id]
                        # 确保学生有enrolled_courses属性
                        if not hasattr(user, 'enrolled_courses'):
                            user.enrolled_courses = []
                        elif isinstance(user.enrolled_courses, list):
                            user.enrolled_courses = list(set(user.enrolled_courses))
                    
                        # 确保课程ID在学生的enrolled_courses中
                        if course.course_id not in user.enrolled_courses:
                            user.enrolled_courses.append(course.course_id)